﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
using System.Diagnostics;

namespace KgUtils.Wpf.Controls
{
    /// <summary>
    /// Radio bouton qui autorise un binding sur un champ de type Enum
    /// <example>
    /// <ctrl:EnumRadioButton EnumValue="{x:Static entities:TypeReaffectation.Commercial}" Content="Commercial" EnumBinding="{Binding EntiteCourante.TypeReaffectation}" />
    /// </example>
    /// <remarks>Attention, il faut absolument que EnumValue soit typé ({x:Static local: MyEnum.Value1}) et non juste une string</remarks>
    /// </summary>
    public class EnumRadioButton : RadioButton
    {
        public EnumRadioButton()
        {
            Loaded += _Loaded;
            Checked += _Checked;
        }

        private void _Loaded(object sender, RoutedEventArgs event_arguments)
        {
            _SetChecked();
        }

        private void _Checked(object sender, RoutedEventArgs event_arguments)
        {
            if (IsChecked == true)
            {
                object binding = EnumBinding;

                //binding == null => signifie que la propriété bindées est un Enum nullable définit actuellement à "null" (donc difficile à contrôler)
                if ((binding is Enum || binding == null) && EnumValue != null)
                {
                    try
                    {
                        //Vérifie que EnumValue existe bien dans EnumBinding, si on peut (donc si EnumBinding n'est pas à null).
                        if (binding != null && Enum.IsDefined(binding.GetType(), EnumValue) || binding == null)
                            EnumBinding = EnumValue;
                        else
                            throw new ArgumentException("EnumValue doesn't exist in the specified EnumBinding Type");
                    }

                    catch (ArgumentException exception)
                    {
                        Debug.WriteLine(
                            string.Format(
                                "EnumRadioButton [{0}]: " +
                                "EnumBinding = {1}, " +
                                "EnumValue = {2}, " +
                                "ArgumentException {3}",
                                Name,
                                EnumBinding,
                                EnumValue,
                                exception));

                        throw;
                    }
                }
            }
        }

        private void _SetChecked()
        {
            object binding = EnumBinding;

            if ((binding is Enum || binding == null) && EnumValue != null)
            {
                try
                {
                    IsChecked = EnumValue.CompareTo((Enum)binding) == 0;
                }

                catch (ArgumentException exception)
                {
                    Debug.WriteLine(
                        string.Format(
                            "EnumRadioButton [{0}]: " +
                            "EnumBinding = {1}, " +
                            "EnumValue = {2}, " +
                            "ArgumentException {3}",
                            Name,
                            EnumBinding,
                            EnumValue,
                            exception));

                    throw;
                }
            }
        }

        static EnumRadioButton()
        {
            FrameworkPropertyMetadata enum_binding_metadata = new FrameworkPropertyMetadata();

            enum_binding_metadata.BindsTwoWayByDefault = true;
            enum_binding_metadata.PropertyChangedCallback = OnEnumBindingChanged;

            EnumBindingProperty = DependencyProperty.Register("EnumBinding",
                                                               typeof(object),
                                                               typeof(EnumRadioButton),
                                                               enum_binding_metadata);

            EnumValueProperty = DependencyProperty.Register("EnumValue",
                                                               typeof(Enum),
                                                               typeof(EnumRadioButton));
        }

        public static readonly DependencyProperty EnumBindingProperty;

        private static void OnEnumBindingChanged(DependencyObject dependency_object, DependencyPropertyChangedEventArgs event_arguments)
        {
            if (dependency_object is EnumRadioButton)
            {
                ((EnumRadioButton)dependency_object)._SetChecked();
            }
        }

        public object EnumBinding
        {
            set { SetValue(EnumBindingProperty, value); }
            get { return (object)GetValue(EnumBindingProperty); }
        }

        public static readonly DependencyProperty EnumValueProperty;

        public Enum EnumValue
        {
            set { SetValue(EnumValueProperty, value); }
            get { return (Enum)GetValue(EnumValueProperty); }
        }
    }
}
